package com.itheima.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.api.CommentsApi;
import com.itheima.api.MovementApi;
import com.itheima.api.UserInfoApi;
import com.itheima.api.VisitorsApi;
import com.itheima.autoconfig.template.OssTemplate;
import com.itheima.domain.Comment;
import com.itheima.domain.Movement;
import com.itheima.domain.UserInfo;
import com.itheima.domain.Visitors;
import com.itheima.enums.CommentType;
import com.itheima.server.exception.BusinessException;
import com.itheima.server.exception.ErrorResult;
import com.itheima.server.interceptor.UserHolder;
import com.itheima.utils.Constants;
import com.itheima.vo.MovementsVo;
import com.itheima.vo.PageResult;
import com.itheima.vo.VisitorsVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @DubboReference
    private MovementApi movementApi;

    @Resource
    private OssTemplate ossTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @DubboReference
    private CommentsApi commentsApi;

    /**
     * 发布动态
     *
     * @param movement
     * @param imageContent
     */
    public void movements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断上传的动态是否为空
        if (StrUtil.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //将文件上传到oss
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //设置动态基本数据
        Long userId = UserHolder.getUserId();
        movement.setUserId(userId);
        movement.setCreated(System.currentTimeMillis());
        movement.setMedias(medias);
        movementApi.publish(movement);
    }

    /**
     * 查看自己动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByUserId(Long userId, Integer page, Integer pagesize) {
        //查询动态信息
        PageResult pageResult = movementApi.findByUserId(userId, page, pagesize);
        List<Movement> items = (List<Movement>) pageResult.getItems();
        if (items == null) {
            return pageResult;
        }
        //获取用户信息
        UserInfo userInfo = userInfoApi.getById(userId);
        //遍历动态数据，将用户信息进行封装
        List<MovementsVo> vo = items.stream().map(item -> {
            //组装vo对象
            return MovementsVo.init(userInfo, item);
        }).collect(Collectors.toList());
        pageResult.setItems(vo);
        return pageResult;
    }

    /**
     * 查询好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult getFriendMovements(Integer page, Integer pagesize) {
        Long userId = UserHolder.getUserId();
        //查询好友动态信息
        List<Movement> movements = movementApi.getFriendMovements(page, pagesize, userId);
        return getPageResult(page, pagesize, movements);
    }

    //抽取获取好友动态方法
    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> movements) {
        if (CollUtil.isEmpty(movements)) {
            return new PageResult();
        }
        //查询发布人的信息
        List<Long> userIds = movements.stream().map(Movement::getUserId).collect(Collectors.toList());
        Map<Long, UserInfo> userInfo = userInfoApi.getByIds(userIds, null);
        //封装对象
        List<MovementsVo> list = new ArrayList<>();
        for (Movement movement : movements) {
            UserInfo info = userInfo.get(movement.getUserId());
            if (info != null) {
                MovementsVo vo = MovementsVo.init(info, movement);
                //点赞
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }
                if (redisTemplate.opsForHash().hasKey(key,loveKey)){
                    vo.setHasLoved(1);
                }
                list.add(vo);
            }
        }
        return new PageResult(page, pagesize, 0, list);
    }


    /**
     * 查看推荐动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult recommend(Integer page, Integer pagesize) {
        //从redis中获取pid列表,解析为集合
        Long userId = UserHolder.getUserId();
        String pidStr = (String) redisTemplate.opsForValue().get(Constants.VIDEOS_RECOMMEND + userId);
        List<Movement> movements = null;
        //判断是否存在推荐id
        if (pidStr == null) {
            //不存在，就随机整10个动态给他
            movements = movementApi.getRandom(10);
        } else {
            String[] split = pidStr.split(",");
            List<Long> pids = Arrays.stream(split).map(Long::parseLong).collect(Collectors.toList());
            //通过pids去查数据
            if ((page - 1) * pagesize < pids.size()){
                pids = pids.stream() .skip((long) (page - 1) * pagesize).limit(pagesize).collect(Collectors.toList());
            }
            movements = movementApi.getRecommend(pids);
        }
        return getPageResult(page,pagesize,movements);
    }


    /**
     * 根据id查询单条动态
     * @param id
     * @return
     */
    public MovementsVo getMovementById(String id) {
        Movement movement = movementApi.getMovementById(id);
        if (movement == null){
            return new MovementsVo();
        }
        //去查userInfo
        UserInfo userInfo = userInfoApi.getById(movement.getUserId());
        return MovementsVo.init(userInfo,movement);
    }


    /**
     * 动态点赞
     * @return
     */
    public Integer like(String movementId) {
        Long userId = UserHolder.getUserId();
        Boolean flag = commentsApi.hasLike(userId,movementId, CommentType.LIKE);
        if (flag){
            //已经点赞
            throw new BusinessException(ErrorResult.likeError());
        }
        //保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentsApi.publishComments(comment);
        //将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;
    }

    /**
     * 取消点赞
     * @return
     */
    public Integer dislike(String movementId) {
        Long userId = UserHolder.getUserId();
        Boolean flag = commentsApi.hasLike(userId,movementId, CommentType.LIKE);
        if (!flag){
            //没点赞，抛异常
            throw new BusinessException(ErrorResult.likeError());
        }
        //删除数据，返回点赞数量
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());
        Integer count = commentsApi.delete(comment);
        //删除redis中的记录
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }

    /**
     * 喜欢
     * @param movementId
     * @return
     */
    public Integer loveComment(String movementId) {
        Long userId = UserHolder.getUserId();
        Boolean flag = commentsApi.hasLike(userId,movementId, CommentType.LOVE);
        if (flag){
            //已经喜欢
            throw new BusinessException(ErrorResult.loveError());
        }
        //保存评论信息
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentsApi.publishComments(comment);
        //将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;
    }


    /**
     * 不喜欢
     * @param movementId
     * @return
     */
    public Integer disloveComment(String movementId) {
        Long userId = UserHolder.getUserId();
        Boolean flag = commentsApi.hasLike(userId,movementId, CommentType.LOVE);
        if (!flag){
            //没喜欢，抛异常
            throw new BusinessException(ErrorResult.loveError());
        }
        //删除数据，返回点赞数量
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());
        Integer count = commentsApi.delete(comment);
        //删除redis中的记录
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }

    /**
     * 谁看过我
     * @return
     */
    public List<VisitorsVo> visitors() {
        //先去redis查询上次访问时间
        Long userId = UserHolder.getUserId();
        Long date = (Long) redisTemplate.opsForHash().get(Constants.VISITORS_USER,userId.toString());
        //查询在当前用户上一次查看访问列表之后，来访问的用户
        List<Visitors> visitors = visitorsApi.visitors(date,UserHolder.getUserId());
        //提取userIds
        List<Long> userIds = visitors.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());
        if (CollUtil.isEmpty(visitors)){
            return new ArrayList<>();
        }
        Map<Long, UserInfo> userInfos = userInfoApi.getByIds(userIds, null);
        List<VisitorsVo> list = new ArrayList<>();
        for (Visitors visitor : visitors) {
            UserInfo userInfo = userInfos.get(visitor.getVisitorUserId());
            if (userInfo != null){
                VisitorsVo vo = VisitorsVo.init(userInfo, visitor);
                list.add(vo);
            }
        }
        return list;
    }


}
























